Linux程序之可变参数&&选项那些事! 您所在的位置:网站首页 m文件生成应用程序 接收命令行 Linux程序之可变参数&&选项那些事!

Linux程序之可变参数&&选项那些事!

2024-03-21 21:35| 来源: 网络整理| 查看: 265

一、linux应用程序如何接收参数? 1. argc、argv

Linux应用程序执行时,我们往往通过命令行带入参数给程序,比如

ls /dev/ -l

其中参数 /dev/ 、-l都是作为参数传递给命令 ls

应用程序又是如何接收这些参数的?

通常应用程序都是从main函数开始执行,传统的main函数风格如下:

int main(int argc, char* argv[]) argc: 程序的命令行参数的数量,用于统计参数数量。 argv: 是一个指向一个字符串数组的指针,数组包含了参数,每个字符串就是一个参数,最后一个元素为0。 过一般习惯使用多级指针来操作字符串。

*char argv[]有时候我们也写成char argv,

**argv[]**是一个存放字符类型元素地址的数组。

因为 C 中是有字符串的概念的:将每个字符存放在 char 数组,最后一个元素为**\0**表示字符串的结束。

**printf(%s)**就是输出字符串。

并且一般使用argv指针来访问、处理argv[]数组的内容。

C语言中,数组就是一个指针加偏移量。

所以argv则是指向一个指针数组argv[]的指针,不用定义,直接可以用。

在argv[]数组中存放的的指针指向输入命令的各部分**(调用程序、选项、参数)**。

2. 举例

下面我们用一个实例来理解argc和argv

/* * argc: 命令行参数的个数 * argv: 字符指针数组(指向各个命令行参数的字符指针所构成的数组) */ int main(int argc, char* argv[]) // 接收命令行参数 { printf("argc=%d\n",argc); for (int i = 0; i 0 && (*++argv)[0] == '-' { while (c = *++argv[0] { switch(c){ case 'x': ... break; case 'n': ... break; default: printf("xxx: illegal opyion %c\n", c); ... break; } } } 3. getopt、getopt_long

事实这么处理选项参数是比较麻烦的,

linux提供了选项解析的函数:

// 头文件 #include #include /*所在头文件 */ int getopt(intargc, char * const argv[], const char *optstring); int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int*longindex); int getopt_long_only(int argc, char * const argv[],const char *optstring, const struct option *longopts, int*longindex); extern char *optarg; /*系统声明的全局变量 */ extern int optind, opterr, optopt; 三、getopt 1. 定义: int getopt(int argc, char * const argv[], const char *optstring); 功能: getopt是用来解析命令行选项参数的,但是只能解析短选项: **-d 100**,不能解析长选项:**--prefix** 参数 argc: main()函数传递过来的参数的个数 argv: main()函数传递过来的参数的字符串指针数组 optstring: 选项字符串,告知 getopt()可以处理哪个选项以及哪个选项需要参数 返回: 如果选项成功找到,返回选项字母;如果所有命令行选项都解析完毕,返回 -1; 如果遇到选项字符不在 optstring 中,返回字符 ‘?’; 如果遇到丢失参数,那么返回值依赖于 optstring 中第一个字符, 如果第一个字符是 ‘:’ 则返回’:‘,否则返回’?'并提示出错误信息。 2. optstring 含义 【重要】

下边重点举例说明optstring的格式意义:

char*optstring = “ab:c::”; 单个字符a 表示选项a没有参数 格式:-a即可,不加参数 单字符加冒号b: 表示选项b有且必须加参数 格式:-b 100或-b100,但-b=100错 单字符加2冒号c:: 表示选项c可以有,也可以无 格式:-c200,其它格式错误

上面这个 optstring 在传入之后,getopt 函数将依次检查命令行是否指定了 -a, -b, -c(这需要多次调用 getopt 函数,直到其返回-1),当检查到上面某一个参数被指定时,函数会返回被指定的参数名称(即该字母)

系统声明的4个全局变量含义如下:

optarg —— 指向当前选项参数(如果有)的指针。 optind —— 再次调用 getopt() 时的下一个 argv指针的索引。 optopt —— 最后一个未知选项。 opterr ­—— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。 3. 实例

说千道万,不如来一个实例:

#include #include #include int main(intargc, char *argv[]) { int opt; char *string = "a::b:c:d"; while ((opt = getopt(argc, argv, string))!= -1) { printf("opt = %c\t\t", opt); printf("optarg = %s\t\t",optarg); printf("optind = %d\t\t",optind); printf("argv[optind] = %s\n",argv[optind]); } } 正确输入参数,执行结果如下: peng@ubuntu:~/work/test$ ./peng -a100 -b 200 -c 300 -d opt = a optarg = 100 optind = 2 argv[optind] = -b opt = b optarg = 200 optind = 4 argv[optind] = -c opt = c optarg = 300 optind = 6 argv[optind] = -d opt = d optarg = (null) optind = 7 argv[optind] = (null)

或者

ork/test$ ./peng -a100 -b200 -c300 -d opt = a optarg = 100 optind = 2 argv[optind] = -b200 opt = b optarg = 200 optind = 3 argv[optind] = -c300 opt = c optarg = 300 optind = 4 argv[optind] = -d opt = d optarg = (null) optind = 5 argv[optind] = (null) 输入选项参数错误的情况 peng@ubuntu:~/work/test$ ./peng -a 100 -b 200 -c 300 -d opt = a optarg = (null) optind = 2 argv[optind] = 100 opt = b optarg = 200 optind = 5 argv[optind] = -c opt = c optarg = 300 optind = 7 argv[optind] = -d opt = d optarg = (null) optind = 8 argv[optind] = (null)

导致解析错误,第一个 optarg = null,实际输入参数 100,由于格式不正确造成的(可选参数格式固定)

参数丢失,也会导致错误 peng@ubuntu:~/work/test$ ./peng -a -b 200 -c opt = a optarg = (null) optind = 2 argv[optind] = -b opt = b optarg = 200 optind = 4 argv[optind] = -c ./peng: option requires an argument -- 'c' opt = ? optarg = (null) optind = 5 argv[optind] = (null)

c选项是必须有参数的

命令行选项未定义,-e选项未在optstring中定义,会报错: peng@ubuntu:~/work/test$ ./peng -t ./peng: invalid option -- 't' opt = ? optarg = (null) optind = 2 argv[optind] = (null) 四、getopt_long 1. 定义: int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts,int *longindex); 功能: 包含 getopt 功能,增加了解析长选项的功能如:--prefix --help 参数: longopts 指明了长参数的名称和属性 longindex 如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是 longopts 的下标值 返回: 对于短选项,返回值同 getopt 函数; 对于长选项, 如果 flag 是 NULL ,返回 val ,否则返回 0 ; 对于错误情况返回值同 getopt 函数 2. struct option struct option { const char *name; /* 参数名称 */ int has_arg; /* 指明是否带有参数 */ int *flag; /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */ int val; /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值 */ };

参数has_arg 说明: has_arg 指明是否带参数值,其数值可选:

no_argument 表明长选项不带参数,如:–name, --help required_argument 表明长选项必须带参数,如:–prefix /root或 --prefix=/root optional_argument 表明长选项的参数是可选的,如:–help或 –prefix=/root,其它都是错误 3. 实例 #include #include #include int main(intargc, char *argv[]) { int opt; int digit_optind = 0; int option_index = 0; char *string = "a::b:c:d"; static struct option long_options[] = { {"reqarg", required_argument,NULL, 'r'}, {"optarg", optional_argument,NULL, 'o'}, {"noarg", no_argument, NULL,'n'}, {NULL, 0, NULL, 0}, }; while((opt =getopt_long_only(argc,argv,string,long_options,&option_index))!= -1) { printf("opt = %c\t\t", opt); printf("optarg = %s\t\t",optarg); printf("optind = %d\t\t",optind); printf("argv[optind] =%s\t\t", argv[optind]); printf("option_index = %d\n",option_index); } } 正确执行命令 peng@ubuntu:~/work/test$ ./long --reqarg 100 --optarg=200 --noarg opt = r optarg = 100 optind = 3 argv[optind] =--optarg=200 option_index = 0 opt = o optarg = 200 optind = 4 argv[optind] =--noarg option_index = 1 opt = n optarg = (null) optind = 5 argv[optind] =(null) option_index = 2

或者

peng@ubuntu:~/work/test$ ./long –reqarg=100 --optarg=200 --noarg opt = o optarg = 200 optind = 3 argv[optind] =--noarg option_index = 1 opt = n optarg = (null) optind = 4 argv[optind] =(null) option_index = 2 可选选项可以不给参数 peng@ubuntu:~/work/test$ ./long --reqarg 100 --optarg --noarg opt = r optarg = 100 optind = 3 argv[optind] =--optarg option_index = 0 opt = o optarg = (null) optind = 4 argv[optind] =--noarg option_index = 1 opt = n optarg = (null) optind = 5 argv[optind] =(null) option_index = 2 输入长选项错误的情况 peng@ubuntu:~/work/test$ ./long --reqarg 100 --optarg 200 --noarg opt = r optarg = 100 optind = 3 argv[optind] =--optarg option_index = 0 opt = o optarg = (null) optind = 4 argv[optind] =200 option_index = 1 opt = n optarg = (null) optind = 6 argv[optind] =(null) option_index = 2 五、getopt_long_only

getopt_long_only 函数与 getopt_long 函数使用相同的参数表,在功能上基本一致

只是 getopt_long 只将 --name 当作长参数,但 getopt_long_only 会将 --name 和 -name 两种选项都当作长参数来匹配

getopt_long_only 如果选项 -name 不能在 longopts 中匹配,但能匹配一个短选项,它就会解析为短选项。

六、综合实例

下面这个例子,是一口君从开源项目ifplug提取出来的命令提取小例子,

大家可以根据自己需要,基于这个框架,定制自己的程序。

#define _GNU_SOURCE #include #include #include #include #include #include #include #define ETHCHECKD_VERSION "1.1" int delay_up = 0; char *interface = "eth0"; void usage(char *p) { if (strrchr(p, '/')) p = strchr(p, '/')+1; printf("%s [options]\n" " -i --iface=IFACE Specify ethernet interface (%s)\n" " -d --delay-up=SECS Specify delay time (%i)\n" " -h --help Show this help\n", p, interface, delay_up); } void parse_args(int argc, char *argv[]) { static struct option long_options[] = { {"iface", required_argument, 0, 'i'}, {"delay-up", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; int option_index = 0; int help = 0, _kill = 0, _check = 0, _version = 0, _suspend = 0, _resume = 0, _info = 0; for (;;) { int c; if ((c = getopt_long(argc, argv, "i:d:hv", long_options, &option_index))


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有